package com.xuanyuanxinyu.utils.crc;

/**
 * 二代数据crc 校验计算 低位在前（8cd5 ==>(byte) 0xd5, (byte) 0x8c）
 *
 * @author wolfman
 */
public class NewTailCrc16 {

    private static final byte[] CRC16_HIGH_TABLE = {
            0, (byte) 193, (byte) 129, 64, 1, (byte) 192, (byte) 128, 65, 1, (byte) 192,
            (byte) 128, 65, 0, (byte) 193, (byte) 129, 64, 1, (byte) 192, (byte) 128, 65,
            0, (byte) 193, (byte) 129, 64, 0, (byte) 193, (byte) 129, 64, 1, (byte) 192,
            (byte) 128, 65, 1, (byte) 192, (byte) 128, 65, 0, (byte) 193, (byte) 129, 64,
            0, (byte) 193, (byte) 129, 64, 1, (byte) 192, (byte) 128, 65, 0, (byte) 193,
            (byte) 129, 64, 1, (byte) 192, (byte) 128, 65, 1, (byte) 192, (byte) 128, 65,
            0, (byte) 193, (byte) 129, 64, 1, (byte) 192, (byte) 128, 65, 0, (byte) 193,
            (byte) 129, 64, 0, (byte) 193, (byte) 129, 64, 1, (byte) 192, (byte) 128, 65,
            0, (byte) 193, (byte) 129, 64, 1, (byte) 192, (byte) 128, 65, 1, (byte) 192,
            (byte) 128, 65, 0, (byte) 193, (byte) 129, 64, 0, (byte) 193, (byte) 129, 64,
            1, (byte) 192, (byte) 128, 65, 1, (byte) 192, (byte) 128, 65, 0, (byte) 193,
            (byte) 129, 64, 1, (byte) 192, (byte) 128, 65, 0, (byte) 193, (byte) 129, 64,
            0, (byte) 193, (byte) 129, 64, 1, (byte) 192, (byte) 128, 65, 1, (byte) 192,
            (byte) 128, 65, 0, (byte) 193, (byte) 129, 64, 0, (byte) 193, (byte) 129, 64,
            1, (byte) 192, (byte) 128, 65, 0, (byte) 193, (byte) 129, 64, 1, (byte) 192,
            (byte) 128, 65, 1, (byte) 192, (byte) 128, 65, 0, (byte) 193, (byte) 129, 64,
            0, (byte) 193, (byte) 129, 64, 1, (byte) 192, (byte) 128, 65, 1, (byte) 192,
            (byte) 128, 65, 0, (byte) 193, (byte) 129, 64, 1, (byte) 192, (byte) 128, 65,
            0, (byte) 193, (byte) 129, 64, 0, (byte) 193, (byte) 129, 64, 1, (byte) 192,
            (byte) 128, 65, 0, (byte) 193, (byte) 129, 64, 1, (byte) 192, (byte) 128, 65,
            1, (byte) 192, (byte) 128, 65, 0, (byte) 193, (byte) 129, 64, 1, (byte) 192,
            (byte) 128, 65, 0, (byte) 193, (byte) 129, 64, 0, (byte) 193, (byte) 129, 64,
            1, (byte) 192, (byte) 128, 65, 1, (byte) 192, (byte) 128, 65, 0, (byte) 193,
            (byte) 129, 64, 0, (byte) 193, (byte) 129, 64, 1, (byte) 192, (byte) 128, 65,
            0, (byte) 193, (byte) 129, 64, 1, (byte) 192, (byte) 128, 65, 1, (byte) 192,
            (byte) 128, 65, 0, (byte) 193, (byte) 129, 64
    };


    private static final byte[] CRC16_LOW_TABLE = {
            0, (byte) 192, (byte) 193, 1, (byte) 195, 3, 2, (byte) 194, (byte) 198,
            6, 7, (byte) 199, 5, (byte) 197, (byte) 196, 4, (byte) 204, 12,
            13, (byte) 205, 15, (byte) 207, (byte) 206, 14, 10, (byte) 202, (byte) 203,
            11, (byte) 201, 9, 8, (byte) 200, (byte) 216, 24, 25, (byte) 217,
            27, (byte) 219, (byte) 218, 26, 30, (byte) 222, (byte) 223, 31, (byte) 221,
            29, 28, (byte) 220, 20, (byte) 212, (byte) 213, 21, (byte) 215, 23,
            22, (byte) 214, (byte) 210, 18, 19, (byte) 211, 17, (byte) 209, (byte) 208,
            16, (byte) 240, 48, 49, (byte) 241, 51, (byte) 243, (byte) 242, 50,
            54, (byte) 246, (byte) 247, 55, (byte) 245, 53, 52, (byte) 244, 60,
            (byte) 252, (byte) 253, 61, (byte) 255, 63, 62, (byte) 254, (byte) 250, 58,
            59, (byte) 251, 57, (byte) 249, (byte) 248, 56, 40, (byte) 232, (byte) 233,
            41, (byte) 235, 43, 42, (byte) 234, (byte) 238, 46, 47, (byte) 239,
            45, (byte) 237, (byte) 236, 44, (byte) 228, 36, 37, (byte) 229, 39,
            (byte) 231, (byte) 230, 38, 34, (byte) 226, (byte) 227, 35, (byte) 225, 33,
            32, (byte) 224, (byte) 160, 96, 97, (byte) 161, 99, (byte) 163, (byte) 162,
            98, 102, (byte) 166, (byte) 167, 103, (byte) 165, 101, 100, (byte) 164,
            108, (byte) 172, (byte) 173, 109, (byte) 175, 111, 110, (byte) 174, (byte) 170,
            106, 107, (byte) 171, 105, (byte) 169, (byte) 168, 104, 120, (byte) 184,
            (byte) 185, 121, (byte) 187, 123, 122, (byte) 186, (byte) 190, 126, 127,
            (byte) 191, 125, (byte) 189, (byte) 188, 124, (byte) 180, 116, 117, (byte) 181,
            119, (byte) 183, (byte) 182, 118, 114, (byte) 178, (byte) 179, 115, (byte) 177,
            113, 112, (byte) 176, 80, (byte) 144, (byte) 145, 81, (byte) 147, 83,
            82, (byte) 146, (byte) 150, 86, 87, (byte) 151, 85, (byte) 149, (byte) 148,
            84, (byte) 156, 92, 93, (byte) 157, 95, (byte) 159, (byte) 158, 94,
            90, (byte) 154, (byte) 155, 91, (byte) 153, 89, 88, (byte) 152, (byte) 136,
            72, 73, (byte) 137, 75, (byte) 139, (byte) 138, 74, 78, (byte) 142,
            (byte) 143, 79, (byte) 141, 77, 76, (byte) 140, 68, (byte) 132, (byte) 133,
            69, (byte) 135, 71, 70, (byte) 134, (byte) 130, 66, 67, (byte) 131,
            65, (byte) 129, (byte) 128, 64
    };

    static byte[] crc8_table = {
            0x00, 0x07, 0x0E, 0x09, 0x1C, 0x1B, 0x12, 0x15, 0x38, 0x3F, 0x36, 0x31, 0x24, 0x23, 0x2A, 0x2D,
            0x70, 0x77, 0x7E, 0x79, 0x6C, 0x6B, 0x62, 0x65, 0x48, 0x4F, 0x46, 0x41, 0x54, 0x53, 0x5A, 0x5D,
            (byte) 0xE0, (byte) 0xE7, (byte) 0xEE, (byte) 0xE9, (byte) 0xFC, (byte) 0xFB, (byte) 0xF2, (byte) 0xF5, (byte) 0xD8, (byte) 0xDF, (byte) 0xD6,
            (byte) 0xD1, (byte) 0xC4, (byte) 0xC3, (byte) 0xCA, (byte) 0xCD,
            (byte) 0x90, (byte) 0x97, (byte) 0x9E, (byte) 0x99, (byte) 0x8C, (byte) 0x8B, (byte) 0x82, (byte) 0x85, (byte) 0xA8, (byte) 0xAF, (byte) 0xA6,
            (byte) 0xA1, (byte) 0xB4, (byte) 0xB3, (byte) 0xBA, (byte) 0xBD,
            (byte) 0xC7, (byte) 0xC0, (byte) 0xC9, (byte) 0xCE, (byte) 0xDB, (byte) 0xDC, (byte) 0xD5, 0x0D, (byte) 0xFF, (byte) 0xF8, (byte) 0xF1, (byte) 0xF6,
            (byte) 0xE3, (byte) 0xE4, (byte) 0xED, (byte) 0xEA,
            (byte) 0xB7, (byte) 0xB0, (byte) 0xB9, (byte) 0xBE, (byte) 0xAB, (byte) 0xAC, (byte) 0xA5, (byte) 0xA2, (byte) 0x8F, (byte) 0x88,
            (byte) 0x81, (byte) 0x86, (byte) 0x93, (byte) 0x94, (byte) 0x9D, (byte) 0x9A,
            0x27, 0x20, 0x29, 0x2E, 0x3B, 0x3C, 0x35, 0x32, 0x1F, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0D, 0x0A,
            0x57, 0x50, 0x59, 0x5E, 0x4B, 0x4C, 0x45, 0x42, 0x6F, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7D, 0x7A,
            (byte) 0x89, (byte) 0x8E, (byte) 0x87, (byte) 0x80, (byte) 0x95, (byte) 0x92,
            (byte) 0x9B, (byte) 0x9C, (byte) 0xB1, (byte) 0xB6, (byte) 0xBF, (byte) 0xB8, (byte) 0xAD, (byte) 0xAA, (byte) 0xA3, (byte) 0xA4,
            (byte) 0xF9, (byte) 0xFE, (byte) 0xF7, (byte) 0xF0, (byte) 0xE5, (byte) 0xE2, (byte) 0xEB,
            (byte) 0xEC, (byte) 0xC1, (byte) 0xC6, (byte) 0xCF, (byte) 0xC8, (byte) 0xDD, (byte) 0xDA, (byte) 0xD3, (byte) 0xD4,
            0x69, 0x6E, 0x67, 0x60, 0x75, 0x72, 0x7B, 0x7C, 0x51, 0x56, 0x5F, 0x58, 0x4D, 0x4A, 0x43, 0x44,
            0x19, 0x1E, 0x17, 0x10, 0x05, 0x02, 0x0B, 0x0C, 0x21, 0x26, 0x2F, 0x28, 0x3D, 0x3A, 0x33, 0x34,
            0x4E, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5C, 0x5B, 0x76, 0x71, 0x78, 0x7F, 0x6A, 0x6D, 0x64, 0x63,
            0x3E, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2C, 0x2B, 0x06, 0x01, 0x08, 0x0F, 0x1A, 0x1D, 0x14, 0x13,
            (byte) 0xAE, (byte) 0xA9, (byte) 0xA0, (byte) 0xA7, (byte) 0xB2, (byte) 0xB5, (byte) 0xBC, (byte) 0xBB, (byte) 0x96, (byte) 0x91, (byte) 0x98,
            (byte) 0x9F, (byte) 0x8A, (byte) 0x8D, (byte) 0x84, (byte) 0x83,
            (byte) 0xDE, (byte) 0xD9, (byte) 0xD0, (byte) 0xD7, (byte) 0xC2, (byte) 0xC5, (byte) 0xCC, (byte) 0xCB, (byte) 0xE6, (byte) 0xE1,
            (byte) 0xE8, (byte) 0xEF, (byte) 0xFA, (byte) 0xFD, (byte) 0xF4, (byte) 0xF3
    };


    public static int getCrc16(byte[] data, int dataLength) {
        byte crc16High = (byte) 0xFF;
        byte crc16Low = (byte) 0xFF;
        for (int i = 0; i < dataLength; ++i) {
            int index = (crc16Low ^ data[i]) & 0xFF;
            crc16Low = (byte) (crc16High ^ CRC16_HIGH_TABLE[index]);
            crc16High = CRC16_LOW_TABLE[index];
        }
        int crc16 = ((crc16High & 0xFF) << 8) + (crc16Low & 0xFF);
        return crc16 ^ 0xFFFF;
    }


    public static int getCrc8(byte[] data, int dataLength) {
        int crc8 = 0;
        for (int i = 0; i < dataLength; ++i) {
            int index = (crc8 ^ data[i]) & 0xFF;
            crc8 = crc8_table[index];
        }
        return crc8;
    }

}
